#ifndef posixtestclient_h__INCLUDED
#define posixtestclient_h__INCLUDED
#define IB_USE_STD_STRING

#include "EWrapper.h"
#include <string.h>

#include <memory>

class EPosixClientSocket;

enum State {
	ST_CONNECT,
	ST_PLACEORDER,
	ST_PLACEORDER_ACK,
	ST_CANCELORDER,
	ST_CANCELORDER_ACK,
	ST_PING,
	ST_PING_ACK,
	ST_REQHISTORICALDATA,
	ST_REQHISTORICALDATA_ACK,
	ST_REQMARKETDATA,
	ST_REQMARKETDATA_ACK,
	ST_IDLE
};

class PairsTradingParam {
//------class to hold parameters used in pairs trading ---------
public:
	bool haveOpenPosition;
	bool readyToTrade;

	std::string top;          //  = "DELL"
	std::string bottom;       //  =  "AMD"

	double ta;				// ask price for top	
	double tb;				// bid price for top
	double ba;				// ask price for bottom
	double bb;				// bid price for bottom

	double ratio0;			// ratio of price when there is no open position
	double ratio1;			// ratio of price when there is no open position
	double ratio0_onOpen;	// ratio of price when there is open position
	double ratio1_onOpen;	// ratio of price when there is open position

	double highVal;			// Cut off to open a short(top)/long(bottom) 
	double lowVal;			// Cut off to open a short(top)/long(bottom) 
	double sellValM;		// Cut off to unwind a open long/short position 
	double buyValM;			// Cut off to unwind a open short/long position 

	double mu;				// Previousely calculated historical mean
	double sigma;			// Previousely claculated historical vol

	int		OpenPosTop;      // Number of open positions in top
	int		OpenPosTopflag;   // long = 1, short =-1
	int		OpenPosBottom;   // Number of open positions in top
	int		OpenPosBottomflag; // long = 1, short =-1
	int		TotalNoOrderPlaced; 

	void ValidateParam() {
	
	if ((ratio0 <=1) || (ratio0 >=0) || (ratio1 <=1) || (ratio1 >=0) || (ratio0_onOpen <=1) || (ratio0_onOpen >=0) || (ratio1_onOpen <=1) || (ratio1_onOpen >=0) )

	readyToTrade= true;	
	
	}

	PairsTradingParam() {
	//	top			="Dell";
	//	bottom		="AMD";

		haveOpenPosition	= false;
		readyToTrade		= false;
		
		highVal		=	0.1;
		lowVal		=	-0.1;
		sellValM	=	0.7;
		buyValM		=	0.7 ; 

		mu			=	0.5327;
		sigma		=	0.03896;	

		ratio0		=	0;			// ratio of price when there is no open position
		ratio1		=	0;			// ratio of price when there is no open position
		ratio0_onOpen	=	0;	// ratio of price when there is open position
		ratio1_onOpen	=	0;	// ratio of price when there is open position

		highVal		=0	;			// Cut off to open a short(top)/long(bottom) 
		lowVal		=0	;			// Cut off to open a short(top)/long(bottom) 
		sellValM	=0	;		// Cut off to unwind a open long/short position 
		buyValM	=0;			// Cut off to unwind a open short/long position 

		OpenPosTop	=0;      // Number of open positions in top
		OpenPosTopflag=	0;   // long = 1, short =-1
		OpenPosBottom=	0;   // Number of open positions in top
		OpenPosBottomflag=	0; // long = 1, short =-1

		ta			=15.21;				// ask price for top	
	    tb			=15.21;				// bid price for top
	    ba			=8.75;				// ask price for bottom
	    bb			=8.75;				// bid price for bottom	
		TotalNoOrderPlaced=0;
	
	}


};


class PosixTestClient : public EWrapper
{
public:

	PosixTestClient();
	~PosixTestClient();

	void processMessages();

public:

	bool connect(const char * host, unsigned int port, int clientId = 0);
	void disconnect() const;
	bool isConnected() const;

private:

	void reqCurrentTime();
	void placeOrder();
	void cancelOrder();
	void reqHistoricalData();


public:
	// events
	void tickPrice(TickerId tickerId, TickType field, double price, int canAutoExecute);
	void tickSize(TickerId tickerId, TickType field, int size);
	void tickOptionComputation( TickerId tickerId, TickType tickType, double impliedVol, double delta,
		double modelPrice, double pvDividend);
	void tickGeneric(TickerId tickerId, TickType tickType, double value);
	void tickString(TickerId tickerId, TickType tickType, const IBString& value);
	void tickEFP(TickerId tickerId, TickType tickType, double basisPoints, const IBString& formattedBasisPoints,
		double totalDividends, int holdDays, const IBString& futureExpiry, double dividendImpact, double dividendsToExpiry);
	void orderStatus(OrderId orderId, const IBString &status, int filled,
		int remaining, double avgFillPrice, int permId, int parentId,
		double lastFillPrice, int clientId, const IBString& whyHeld);
	void openOrder(OrderId orderId, const Contract&, const Order&, const OrderState&);
	void openOrderEnd();
	void winError(const IBString &str, int lastError);
	void connectionClosed();
	void updateAccountValue(const IBString& key, const IBString& val,
		const IBString& currency, const IBString& accountName);
	void updatePortfolio(const Contract& contract, int position,
		double marketPrice, double marketValue, double averageCost,
		double unrealizedPNL, double realizedPNL, const IBString& accountName);
	void updateAccountTime(const IBString& timeStamp);
	void accountDownloadEnd(const IBString& accountName);
	void nextValidId(OrderId orderId);
	void contractDetails(int reqId, const ContractDetails& contractDetails);
	void bondContractDetails(int reqId, const ContractDetails& contractDetails);
	void contractDetailsEnd(int reqId);
	void execDetails(int reqId, const Contract& contract, const Execution& execution);
	void execDetailsEnd(int reqId);
	void error(const int id, const int errorCode, const IBString errorString);
	void updateMktDepth(TickerId id, int position, int operation, int side,
		double price, int size);
	void updateMktDepthL2(TickerId id, int position, IBString marketMaker, int operation,
		int side, double price, int size);
	void updateNewsBulletin(int msgId, int msgType, const IBString& newsMessage, const IBString& originExch);
	void managedAccounts(const IBString& accountsList);
	void receiveFA(faDataType pFaDataType, const IBString& cxml);
	void historicalData(TickerId reqId, const IBString& date, double open, double high,
		double low, double close, int volume, int barCount, double WAP, int hasGaps);
	void scannerParameters(const IBString &xml);
	void scannerData(int reqId, int rank, const ContractDetails &contractDetails,
		const IBString &distance, const IBString &benchmark, const IBString &projection,
		const IBString &legsStr);
	void scannerDataEnd(int reqId);
	void realtimeBar(TickerId reqId, long time, double open, double high, double low, double close,
		long volume, double wap, int count);
	void currentTime(long time);
	void fundamentalData(TickerId reqId, const IBString& data);
	void deltaNeutralValidation(int reqId, const UnderComp& underComp);
	void tickSnapshotEnd(int reqId);

	//------------User Added code for pairs trading ------------
	void PosixTestClient::placeOrderBuyDell();
	void PosixTestClient::iniPairsTrading();
	void PosixTestClient::reqHistoricalDataDell();
	void PosixTestClient::reqHistoricalDataAMD();
	void PosixTestClient::BuytopSellBottom_toOpen();
	void PosixTestClient::BuyTopSellBottom_toOpen();
	void PosixTestClient::BuytopSellBottom_toClose();
	void PosixTestClient::SelltopBuyBottom_toClose();
	void PosixTestClient::PrintAllParams();
	void reqMktDataDell();
	void reqMktDataAMD();
	void ValidateParam();



private:

	std::auto_ptr<EPosixClientSocket> m_pClient;
	State m_state;
	time_t m_sleepDeadline;
	OrderId m_orderId;

	//------------Instance of pairs trading parameter ------------
	PairsTradingParam m_PairsTrading_Param;
};

#endif

